package com.ssm.basis.service.dictionary;

import com.baomidou.mybatisplus.annotation.EnumValue;
import com.baomidou.mybatisplus.annotation.IEnum;
import com.fasterxml.jackson.annotation.*;
import lombok.AllArgsConstructor;
import lombok.Getter;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static com.ssm.basis.service.constant.SecurityConstant.SUPPRESS_WARNING_ALL;

// @JsonFormat(shape = JsonFormat.Shape.OBJECT)
public interface DictEnum extends IEnum<String> {
    @Override
    String getValue(); // code，数据库存的值

    @JsonValue
    String getDesc(); // name，json 序列化的值

    /**
     * 根据 value 获取枚举
     * <T extends Enum<?> & BaseEnum>: E 必须为一个枚举类，同时还必须实现 BaseEnum 接口
     */
    static <T extends Enum<?> & DictEnum> Optional<T> getEnumByValue(Class<T> enumClass, String value) {
        return Stream.of(enumClass.getEnumConstants()).filter(enumerator -> Objects.equals(enumerator.getValue(), value)).findAny();
    }

    /**
     * 枚举转 Map
     */
    static <E extends Enum<?> & DictEnum> Map<String, String> enumToMap(Class<E> clazz) {
        return Arrays.stream(clazz.getEnumConstants()).collect(Collectors.toMap(DictEnum::getValue, DictEnum::getDesc, (u, v) -> {
            throw new IllegalStateException(String.format("Duplicate key %s", u)); // 合并时检查 key 是否重复
        }, LinkedHashMap::new));
    }

    /**
     * 根据 value 获取 Desc
     */
    @SuppressWarnings(SUPPRESS_WARNING_ALL)
    static <T extends Enum<?> & DictEnum> String getDescByValue(Class<T> enumClass, String value) {
        return getEnumByValue(enumClass, value).orElse((T) EmptyEnum.EMPTY).getDesc();
    }

    default boolean equalsValue(String value) {
        return this.getValue().equals(value);
    }

    default boolean isNotEquals(DictEnum dictEnum) {
        return this != dictEnum;
    }

    @Getter
    @AllArgsConstructor
    enum EmptyEnum implements DictEnum {
        EMPTY(null, ""),
        @JsonEnumDefaultValue
        NULL(null, null);
        @JsonAlias("code")
        @EnumValue // 标记数据库存的值
        final String value;
        @JsonAlias("name")
        @JsonValue // 标记响应 json 值
        final String desc;

        @JsonCreator
        EmptyEnum JsonCreator(@JsonProperty("value") String value) {
            for (EmptyEnum e : values()) if (e.getValue().equals(value)) return e;
            throw new IllegalArgumentException("Unknown value: " + value);
        }
    }
}